package convertor

import (
	"errors"
	"github.com/jinzhu/copier"
	"gotham-plan-manage/internal/domain/model/plan-aggregate/aggregate"
	entity2 "gotham-plan-manage/internal/domain/model/plan-aggregate/entity"
	valueobject2 "gotham-plan-manage/internal/domain/model/plan-aggregate/valueobject"
	"gotham-plan-manage/internal/infra/database/mysql/plan/po"
	"gotham-plan-manage/pkg/consts"
	"time"
)

/*
   @author:zhongyang
   @date:2023/4/2
   @description:计划管理-数据库对象和领域对象转换器
*/

type Option func(aggregate *aggregate.PlanAggregate)

type PlanManageConvertor struct {
}

func NewPlanManageConvertor() *PlanManageConvertor {
	return &PlanManageConvertor{}
}

// CreatePlanAggregateByOption 使用Option模式灵活创建计划聚合根
func (p *PlanManageConvertor) CreatePlanAggregateByOption(opts ...Option) *aggregate.PlanAggregate {
	plan := &aggregate.PlanAggregate{
		ExtendDetail: &valueobject2.PlanExtendDetail{},
		PlanDetail:   &entity2.PlanDetail{},
		PlanReport:   &valueobject2.PlanReport{},
	}
	for _, opt := range opts {
		opt(plan)
	}
	return plan
}

func WithPlanPO(planPO *po.PlanPO) Option {
	return func(aggregate *aggregate.PlanAggregate) {
		if planPO == nil {
			return
		}
		_ = copier.Copy(&aggregate, planPO)
	}
}

func WithPlanDetailPO(planDetailPO *po.PlanDetailPO) Option {
	return func(aggregate *aggregate.PlanAggregate) {
		if planDetailPO == nil {
			return
		}
		aggregate.PlanDetail.Target = planDetailPO.Target
	}
}

func WithPlanReportPO(reportPO *po.PlanReportPO) Option {
	return func(aggregate *aggregate.PlanAggregate) {
		if reportPO == nil {
			return
		}
		aggregate.PlanReport.ReportId = reportPO.ReportId
		aggregate.PlanReport.IsOverTime = reportPO.IsOverTime
		aggregate.PlanReport.TaskTotal = reportPO.TaskTotal
		aggregate.PlanReport.RealDay = reportPO.RealDay
		aggregate.PlanReport.ExpectDay = reportPO.ExpectDay
	}
}

func WithTaskPO(taskPO *po.TaskPO) Option {
	return func(aggregate *aggregate.PlanAggregate) {
		if taskPO == nil {
			return
		}
		taskEntity := &entity2.Task{
			TaskId:      taskPO.TodoTaskId,
			Think:       taskPO.Think,
			ExecuteDate: taskPO.ExecuteDate,
			PlanId:      taskPO.PlanId,
		}
		aggregate.Tasks = append(aggregate.Tasks, taskEntity)
	}
}

func WithTaskPOs(taskPOs []*po.TaskPO) Option {
	return func(aggregate *aggregate.PlanAggregate) {
		if len(taskPOs) == 0 {
			return
		}
		for _, taskPO := range taskPOs {
			taskEntity := &entity2.Task{
				TaskId:      taskPO.TodoTaskId,
				Think:       taskPO.Think,
				ExecuteDate: taskPO.ExecuteDate,
				IsNew:       false,
				PlanId:      taskPO.PlanId,
			}
			for _, taskItemPO := range taskPO.TaskItemPOs {
				taskItemEntity := &entity2.TaskItem{
					Id:         taskItemPO.TaskItemId,
					Content:    taskItemPO.Content,
					Level:      taskItemPO.Level,
					FinishDate: taskItemPO.FinishDate,
				}
				taskEntity.TaskItems = append(taskEntity.TaskItems, taskItemEntity)
			}
			aggregate.Tasks = append(aggregate.Tasks, taskEntity)
		}
	}
}

func WithTaskItemPOs(taskItemPOs []*po.TaskItemPO) Option {
	return func(aggregate *aggregate.PlanAggregate) {
		if len(taskItemPOs) == 0 {
			return
		}
		if len(aggregate.Tasks) == 0 {
			return
		}
		for _, task := range aggregate.Tasks {
			if task.TaskId == taskItemPOs[0].TodoTaskId {
				for _, itemPO := range taskItemPOs {
					item := &entity2.TaskItem{
						Id:         itemPO.TaskItemId,
						Content:    itemPO.Content,
						Level:      itemPO.Level,
						FinishDate: itemPO.FinishDate,
					}
					task.TaskItems = append(task.TaskItems, item)
				}
			}
		}
	}
}

func WithQuestionPOs(questionPOs []*po.QuestionPO) Option {
	return func(aggregate *aggregate.PlanAggregate) {
		if len(questionPOs) == 0 {
			return
		}
		copier.Copy(&aggregate.Questions, questionPOs)
	}
}

func (p *PlanManageConvertor) CreatePlanPO(aggregate *aggregate.PlanAggregate) *po.PlanPO {
	return &po.PlanPO{
		PlanId:     aggregate.PlanId,
		Name:       aggregate.Name,
		CreateDate: time.Now().Format("2006-01-02"),
		StartDate:  aggregate.StartDate,
		EndDate:    aggregate.EndDate,
		FinishDate: consts.DefaultDate,
		UserId:     aggregate.UserId,
		ParentId:   aggregate.ParentId,
	}
}

// CreatePlanDetailPO 创建计划详情的PO
func (p *PlanManageConvertor) CreatePlanDetailPO(aggregate *aggregate.PlanAggregate) *po.PlanDetailPO {
	return &po.PlanDetailPO{
		PlanId: aggregate.PlanId,
		Target: aggregate.PlanDetail.Target,
	}
}

// DeletePlanDetailPO 删除计划详情的PO
func (p *PlanManageConvertor) DeletePlanDetailPO(aggregate *aggregate.PlanAggregate) *po.PlanDetailPO {
	return &po.PlanDetailPO{
		PlanId: aggregate.PlanId,
	}
}

// EditPlanDetailPO 修改计划详情的PO
func (p *PlanManageConvertor) EditPlanDetailPO(aggregate *aggregate.PlanAggregate) *po.PlanDetailPO {
	return &po.PlanDetailPO{
		PlanId: aggregate.PlanId,
		Target: aggregate.PlanDetail.Target,
	}
}

// DeletePlanPO 删除计划的PO
func (p *PlanManageConvertor) DeletePlanPO(aggregate *aggregate.PlanAggregate) *po.PlanPO {
	return &po.PlanPO{
		PlanId: aggregate.PlanId,
	}
}

func (p *PlanManageConvertor) DeleteTaskPO(plan *aggregate.PlanAggregate) *po.TaskPO {
	return &po.TaskPO{PlanId: plan.PlanId}
}

func (p *PlanManageConvertor) DeleteTaskItemPO(plan *aggregate.PlanAggregate) *po.TaskItemPO {
	return &po.TaskItemPO{PlanId: plan.PlanId}
}

func (p *PlanManageConvertor) EditPlanPO(planAggregate *aggregate.PlanAggregate) *po.PlanPO {
	return &po.PlanPO{
		PlanId:    planAggregate.PlanId,
		Name:      planAggregate.Name,
		StartDate: planAggregate.StartDate,
		EndDate:   planAggregate.EndDate,
		ParentId:  planAggregate.ParentId,
	}
}

func (p *PlanManageConvertor) DeletePlanReportPO(plan *aggregate.PlanAggregate) *po.PlanReportPO {
	return &po.PlanReportPO{
		PlanId: plan.PlanId,
	}
}

func (p *PlanManageConvertor) DeleteQuestionPO(plan *aggregate.PlanAggregate) *po.QuestionPO {
	return &po.QuestionPO{
		PlanId: plan.PlanId,
	}
}

func (p *PlanManageConvertor) CreatePlanReportPO(plan *aggregate.PlanAggregate) *po.PlanReportPO {
	return &po.PlanReportPO{
		ReportId:   plan.PlanReport.ReportId,
		PlanId:     plan.PlanId,
		PlanName:   plan.Name,
		FinishDate: plan.FinishDate,
		IsOverTime: plan.PlanReport.IsOverTime,
		ExpectDay:  plan.PlanReport.ExpectDay,
		RealDay:    plan.PlanReport.RealDay,
		TaskTotal:  plan.PlanReport.TaskTotal,
	}
}

func (p *PlanManageConvertor) CreateTaskPO(plan *aggregate.PlanAggregate) (*po.TaskPO, error) {
	if len(plan.Tasks) == 0 {
		return nil, errors.New("未创建待办")
	}
	return &po.TaskPO{
		TodoTaskId:  plan.Tasks[0].TaskId,
		ExecuteDate: plan.Tasks[0].ExecuteDate,
		UserId:      plan.UserId,
		PlanId:      plan.PlanId,
	}, nil
}

func (p *PlanManageConvertor) CreateTaskItemPO(plan *aggregate.PlanAggregate) (*po.TaskItemPO, error) {
	if len(plan.Tasks) == 0 || len(plan.Tasks[0].TaskItems) == 0 {
		return nil, errors.New("未创建待办或者未创建待办项")
	}
	return &po.TaskItemPO{
		TaskItemId: plan.Tasks[0].TaskItems[0].Id,
		Content:    plan.Tasks[0].TaskItems[0].Content,
		TodoTaskId: plan.Tasks[0].TaskId,
		Level:      plan.Tasks[0].TaskItems[0].Level,
		PlanId:     plan.PlanId,
		FinishDate: plan.Tasks[0].TaskItems[0].FinishDate,
	}, nil
}

func (p *PlanManageConvertor) FinishTaskItemPO(plan *aggregate.PlanAggregate) *po.TaskItemPO {
	return &po.TaskItemPO{
		TaskItemId: plan.Tasks[0].TaskItems[0].Id,
		Content:    plan.Tasks[0].TaskItems[0].Content,
		TodoTaskId: plan.Tasks[0].TaskId,
		Level:      plan.Tasks[0].TaskItems[0].Level,
		PlanId:     plan.PlanId,
		FinishDate: plan.Tasks[0].TaskItems[0].FinishDate,
	}
}

func (p *PlanManageConvertor) EditTaskItemPO(item *entity2.TaskItem) *po.TaskItemPO {
	return &po.TaskItemPO{
		TaskItemId: item.Id,
		Content:    item.Content,
		Level:      item.Level,
		FinishDate: item.FinishDate,
	}
}

func (p *PlanManageConvertor) EditTaskAndItemPO(plan *aggregate.PlanAggregate) []*po.TaskPO {
	var taskRes []*po.TaskPO
	for _, task := range plan.Tasks {
		taskPO := &po.TaskPO{
			TodoTaskId:  task.TaskId,
			Think:       task.Think,
			ExecuteDate: task.ExecuteDate,
			UserId:      plan.UserId,
			PlanId:      plan.PlanId,
		}
		taskRes = append(taskRes, taskPO)
		for _, item := range task.TaskItems {
			itemPO := &po.TaskItemPO{
				TaskItemId: item.Id,
				Content:    item.Content,
				TodoTaskId: task.TaskId,
				Level:      item.Level,
				PlanId:     plan.PlanId,
				FinishDate: item.FinishDate,
			}
			taskPO.TaskItemPOs = append(taskPO.TaskItemPOs, itemPO)
		}
	}
	return taskRes
}

func (p *PlanManageConvertor) ConvertQuestionPO(questions []*entity2.Question) []*po.QuestionPO {
	var res []*po.QuestionPO
	for _, question := range questions {
		item := &po.QuestionPO{}
		copier.Copy(&item, question)
		res = append(res, item)
	}
	return res
}

func (p *PlanManageConvertor) ConvertPO2TaskItemEntities(itemPOs []*po.TaskItemPO) []*entity2.TaskItem {
	var res []*entity2.TaskItem
	for _, itemPO := range itemPOs {
		item := &entity2.TaskItem{
			Id:         itemPO.TaskItemId,
			Content:    itemPO.Content,
			Level:      itemPO.Level,
			FinishDate: itemPO.FinishDate,
		}
		res = append(res, item)
	}
	return res
}

func (p *PlanManageConvertor) ConvertPO2TaskEntities(taskPOs []*po.TaskPO) []*entity2.Task {
	var res []*entity2.Task
	for _, taskPO := range taskPOs {
		item := &entity2.Task{
			TaskId:      taskPO.TodoTaskId,
			Think:       taskPO.Think,
			ExecuteDate: taskPO.ExecuteDate,
			PlanId:      taskPO.PlanId,
			IsNew:       false,
		}
		res = append(res, item)
	}
	return res
}

func (p *PlanManageConvertor) FinishPlanPO(plan *aggregate.PlanAggregate) *po.PlanPO {
	return &po.PlanPO{
		PlanId:     plan.PlanId,
		FinishDate: plan.FinishDate,
	}
}
